#! /bin/sh /usr/share/dpatch/dpatch-run
## 45_studiolevels.dpatch by Jean-Yves Avenard <jean-yves@avenard.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad mythtv-0.22.0-fixes22824~/libs/libmythtv/util-vdpau.cpp mythtv-0.22.0-fixes22824/libs/libmythtv/util-vdpau.cpp
--- mythtv-0.22.0-fixes22824~/libs/libmythtv/util-vdpau.cpp	2009-11-07 12:41:57.000000000 +0100
+++ mythtv-0.22.0-fixes22824/libs/libmythtv/util-vdpau.cpp	2009-11-14 11:32:13.000000000 +0100
@@ -81,8 +81,9 @@
     deinterlacer("notset"), deinterlacing(false), currentFrameNum(-1),
     needDeintRefs(false),   deintLock(QMutex::Recursive), skipChroma(0),
     numRefs(0),             denoise(0.0f),          sharpen(0.0f),
-    useColorControl(false), pipOutputSurface(0),
-    pipAlpha(0),            pipBorder(0),
+    useColorControl(false), colorspace(VDP_COLOR_STANDARD_ITUR_BT_601),
+    studio(false),
+    pipOutputSurface(0),    pipAlpha(0),       pipBorder(0),
     pipClear(0),            pipReady(0),       pipNeedsClear(false),
     vdp_flip_target(0),     vdp_flip_queue(0), vdpauDecode(false),
     vdp_device(0),          errorCount(0),     errorState(kError_None),
@@ -154,7 +155,7 @@
     if (!ok)
         return ok;
 
-    if (color_control)
+    if (color_control || studio || colorspace < 0 || colorspace==VDP_COLOR_STANDARD_ITUR_BT_709)
         useColorControl = InitColorControl();
 
     return ok;
@@ -1745,6 +1746,11 @@
     return ok;
 }
 
+#define COL_Y 0
+#define COL_U 1
+#define COL_V 2
+#define COL_C 3
+
 bool VDPAUContext::SetPictureAttributes(void)
 {
     bool ok = true;
@@ -1753,12 +1759,58 @@
     if (!videoMixer || !useColorControl)
         return false;
 
-    vdp_st = vdp_generate_csc_matrix(
-        &proCamp,
-        VDP_COLOR_STANDARD_ITUR_BT_601, // detect?
-        &cscMatrix
-    );
-    CHECK_ST
+    if (colorspace < 0)
+    {
+        colorspace = (videoSize.width() >= 1280 || videoSize.height() > 576) ?
+                      VDP_COLOR_STANDARD_ITUR_BT_709 :
+                      VDP_COLOR_STANDARD_ITUR_BT_601;
+        VERBOSE(VB_PLAYBACK, LOC + QString("Using ITU %1 colorspace")
+                    .arg((colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
+                    "BT.601" : "BT.709"));
+    }
+
+    if (studio)
+    {
+        static const float color_coeffs[][3] = {{ 0.299, 0.587, 0.114},
+                                                { 0.2125, 0.7154, 0.0721}};
+        int csp = (colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ? 0 : 1;
+        float uvcos = proCamp.saturation * cos(proCamp.hue);
+        float uvsin = proCamp.saturation * sin(proCamp.hue);
+        float Kr, Kg, Kb;
+        int rgbmin = 16;
+        int rgbr = 235-16;
+
+        Kr = color_coeffs[csp][0];
+        Kg = color_coeffs[csp][1];
+        Kb = color_coeffs[csp][2];
+
+        float uv_coeffs[3][2] = {
+            { 0.000,                      (rgbr/112.0)*(1-Kr)       },
+            {-(rgbr/112.0)*(1-Kb)*Kb/Kg, -(rgbr/112.0)*(1-Kr)*Kr/Kg },
+            { (rgbr/112.0)*(1-Kb),        0.000                     }
+        };
+
+        for (int i = 0; i < 3; i++)
+        {
+            cscMatrix[i][COL_C]  = proCamp.brightness;
+            cscMatrix[i][COL_Y]  = rgbr * proCamp.contrast / 219;
+            cscMatrix[i][COL_C] += (-16 / 255.0) * cscMatrix[i][COL_Y];
+            cscMatrix[i][COL_U]  = uv_coeffs[i][0] * uvcos + uv_coeffs[i][1] * uvsin;
+            cscMatrix[i][COL_C] += (-128 / 255.0) * cscMatrix[i][COL_U];
+            cscMatrix[i][COL_V]  = uv_coeffs[i][0] * uvsin + uv_coeffs[i][1] * uvcos;
+            cscMatrix[i][COL_C] += (-128 / 255.0) * cscMatrix[i][COL_V];
+            cscMatrix[i][COL_C] += rgbmin / 255.0;
+            cscMatrix[i][COL_C] += 0.5 - proCamp.contrast / 2.0;
+        }
+    }
+    else
+    {
+        vdp_st = vdp_generate_csc_matrix(
+            &proCamp,
+            colorspace,
+            &cscMatrix);
+        CHECK_ST
+    }
 
     VdpVideoMixerAttribute attributes[] = {
         VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX
@@ -2145,13 +2197,14 @@
 void VDPAUContext::ParseOptions(QString options)
 {
     QStringList list = options.split(",");
+
     if (list.empty())
         return;
 
     for (QStringList::Iterator i = list.begin(); i != list.end(); ++i)
     {
-        QString name = (*i).section('=', 0, 0);
-        QString opts = (*i).section('=', 1);
+        QString name = (*i).section('=', 0, 0).toLower();
+        QString opts = (*i).section('=', 1).toLower();
 
         if (name.contains("vdpauivtc"))
         {
@@ -2191,5 +2244,32 @@
                 mixerFeatures |= kVDP_FEAT_SHARPNESS;
             }
         }
+
+        if (name.contains("colorspace"))
+        {
+            int tmp;
+
+            if (opts.contains("auto"))
+                colorspace = -1;
+            else if (opts.contains("601"))
+                colorspace = VDP_COLOR_STANDARD_ITUR_BT_601;
+            else if (opts.contains("709"))
+                colorspace = VDP_COLOR_STANDARD_ITUR_BT_709;
+
+            if (colorspace > -1)
+            {
+                VERBOSE(VB_PLAYBACK, LOC +
+                    QString("Forcing ITU BT.%1 colorspace")
+                    .arg((colorspace == VDP_COLOR_STANDARD_ITUR_BT_601) ?
+                    "BT.601" : "BT.709"));
+            }
+        }
+
+        if (name.contains("studio"))
+        {
+            VERBOSE(VB_PLAYBACK, LOC +
+                    QString("Enabling Studio Levels [16-235]."));
+            studio = true;
+        }
     }
 }
diff -urNad mythtv-0.22.0-fixes22824~/libs/libmythtv/util-vdpau.h mythtv-0.22.0-fixes22824/libs/libmythtv/util-vdpau.h
--- mythtv-0.22.0-fixes22824~/libs/libmythtv/util-vdpau.h	2009-11-07 12:41:57.000000000 +0100
+++ mythtv-0.22.0-fixes22824/libs/libmythtv/util-vdpau.h	2009-11-14 11:29:35.000000000 +0100
@@ -164,10 +164,12 @@
     int               numRefs;
     float             denoise;
     float             sharpen;
-
+   
     bool              useColorControl;
     VdpCSCMatrix      cscMatrix;
     VdpProcamp        proCamp;
+    int               colorspace;
+    bool              studio;
 
     VdpLayer          pipLayer;
     VdpOutputSurface  pipOutputSurface;
